#ifndef   M_Code_EDITOR_H
#define   M_Code_EDITOR_H

#include <wx/hashmap.h>
#include <wx/datetime.h>
#include <wx/fontmap.h>
#include <wx/timer.h>
#include "editorbase.h"

extern const wxString g_EditorModified;
struct M_Code_EditorInternalData;
class M_Code_Editor;
class ProjectFile;
class EditorColourSet;
class wxSplitterWindow;
class LoaderBase;
class M_Code_StyledTextCtrl;
class wxScintillaEvent;
class wxBoxSizer;

class M_Code_Editor : public EditorBase {
    DECLARE_EVENT_TABLE()
    friend class EditorManager;
  protected:
    M_Code_Editor( wxWindow* parent, const wxString& filename, EditorColourSet* theme = nullptr );
    M_Code_Editor( wxWindow* parent, LoaderBase* fileLdr, const wxString& filename, EditorColourSet* theme = nullptr );
    ~M_Code_Editor();
  public:
    enum SplitType {
      stNoSplit = 0,
      stHorizontal,
      stVertical
    };
    void operator=( M_Code_unused const M_Code_Editor& rhs ) { m_Throw( _T( "Can't assign an cbEditor* !!!" ) ); }
    M_Code_StyledTextCtrl* GetControl() const;
    M_Code_StyledTextCtrl* GetLeftSplitViewControl() const { return m_pControl; }
    M_Code_StyledTextCtrl* GetRightSplitViewControl() const { return m_pControl2; }
    SplitType GetSplitType() const { return m_SplitType; }
    bool IsOK() const { return m_IsOK; }
    void SetEditorTitle( const wxString& title );
    bool GetModified() const;
    void SetModified( bool modified = true );
    void SetProjectFile( ProjectFile* project_file, bool preserve_modified = false );
    ProjectFile* GetProjectFile() const { return m_pProjectFile; }
    void UpdateProjectFile();
    bool Save();
    bool SaveAs();
    bool SaveFoldState();
    bool FixFoldState();
    void FoldAll();
    void UnfoldAll();
    void ToggleAllFolds();
    void SetFoldingIndicator();
    void FoldBlockFromLine( int line = -1 );
    void UnfoldBlockFromLine( int line = -1 );
    void ToggleFoldBlockFromLine( int line = -1 );
    void SetColourSet( EditorColourSet* theme );
    EditorColourSet* GetColourSet() const { return m_pTheme; }
    void GotoMatchingBrace();
    void HighlightBraces();
    int GetLineIndentInSpaces( int line = -1 ) const;
    wxString GetLineIndentString( int line = -1 ) const;
    wxDateTime GetLastModificationTime() const { return m_LastModified; }
    void Touch();
    bool Reload( bool detectEncoding = true );
    void AutoComplete();
    void GotoLine( int line, bool centerOnScreen = true );
    bool GotoTokenPosition( int line, const wxString& tokenName );
    bool AddBreakpoint( int line = -1, bool notifyDebugger = true );
    bool RemoveBreakpoint( int line = -1, bool notifyDebugger = true );
    virtual void ToggleBreakpoint( int line = -1, bool notifyDebugger = true );
    virtual bool HasBreakpoint( int line ) const;
    virtual void GotoNextBreakpoint();
    virtual void GotoPreviousBreakpoint();
    virtual void RefreshBreakpointMarkers();
    virtual void ClearAllBookmarks();
    virtual void ToggleBookmark( int line = -1 );
    virtual bool HasBookmark( int line ) const;
    virtual void GotoNextBookmark();
    virtual void GotoPreviousBookmark();
    virtual void SetDebugLine( int line );
    virtual void SetErrorLine( int line );
    void Split( SplitType split );
    void Unsplit();
    void Undo();
    void Redo();
    void ClearHistory();
    void GotoNextChanged();
    void GotoPreviousChanged();
    void SetChangeCollection( bool collectChange );
    void Cut();
    void Copy();
    void Paste();
    bool CanUndo() const;
    bool CanRedo() const;
    bool HasSelection() const;
    bool CanPaste() const;
    bool IsReadOnly() const;
    void SetReadOnly( bool readonly = true );
    bool CanSelectAll() const;
    void SelectAll();
    void DoIndent();
    void DoUnIndent();
    virtual void AddToContextMenu( wxMenu* popup, ModuleType type );
    HighlightLanguage GetLanguage() const { return m_lang; }
    void SetLanguage( HighlightLanguage lang = HL_AUTO );
    wxFontEncoding GetEncoding() const;
    wxString GetEncodingName() const;
    void SetEncoding( wxFontEncoding encoding );
    bool GetUseBom() const;
    void SetUseBom( bool bom );
    void SetZoom( int zoom, bool both = true );
    static void ApplyStyles( M_Code_StyledTextCtrl* control );
    void AutoIndentDone();
    void SetEditorStyle();
  private:
    M_Code_Editor( M_Code_unused const M_Code_Editor& rhs );
    bool LineHasMarker( int marker, int line = -1 ) const;
    void MarkerToggle( int marker, int line = -1 );
    void MarkerNext( int marker );
    void MarkerPrevious( int marker );
    void MarkLine( int marker, int line );
    void DoFoldAll( int fold );
    void DoFoldBlockFromLine( int line, int fold );
    bool DoFoldLine( int line, int fold );
    void SetMarkerStyle( int marker, int markerType, wxColor fore, wxColor back );
    void UnderlineFoldedLines( bool underline );
    M_Code_StyledTextCtrl* CreateEditor();
    void ConnectEvents( M_Code_StyledTextCtrl* stc );
    void SetEditorStyleBeforeFileOpen();
    void SetEditorStyleAfterFileOpen();
    static void InternalSetEditorStyleBeforeFileOpen( M_Code_StyledTextCtrl* control );
    static void InternalSetEditorStyleAfterFileOpen( M_Code_StyledTextCtrl* control );
    bool Open( bool detectEncoding = true );
    void DoAskForCodeCompletion();
    static wxColour GetOptionColour( const wxString& option, const wxColour _default );
    void NotifyPlugins( wxEventType type, int intArg = 0, const wxString& strArg = wxEmptyString, int xArg = 0, int yArg = 0 );
    void OnMarginClick( wxScintillaEvent& event );
    void OnEditorUpdateUI( wxScintillaEvent& event );
    void OnEditorChange( wxScintillaEvent& event );
    void OnEditorCharAdded( wxScintillaEvent& event );
    void OnEditorDwellStart( wxScintillaEvent& event );
    void OnEditorDwellEnd( wxScintillaEvent& event );
    void OnEditorModified( wxScintillaEvent& event );
    void OnUserListSelection( wxScintillaEvent& event );
    void OnZoom( wxScintillaEvent& event );
    void OnScintillaEvent( wxScintillaEvent& event );
    void OnClose( wxCloseEvent& event );
    void OnContextMenuEntry( wxCommandEvent& event );
    bool OnBeforeBuildContextMenu( const wxPoint& position, ModuleType type );
    void DestroySplitView();
    void DoInitializations( const wxString& filename, LoaderBase* fileLdr = nullptr );
    void BreakpointMarkerToggle( int line );
    bool m_IsOK;
    wxSplitterWindow* m_pSplitter;
    wxBoxSizer* m_pSizer;
    M_Code_StyledTextCtrl* m_pControl;
    M_Code_StyledTextCtrl* m_pControl2;
    M_Code_StyledTextCtrl* m_foldBackup;
    SplitType m_SplitType;
    bool m_Modified;
    int m_Index;
    wxTimer m_timerWait;
    ProjectFile* m_pProjectFile;
    EditorColourSet* m_pTheme;
    HighlightLanguage m_lang;
    wxDateTime m_LastModified;
    bool m_autoIndentDone;
    friend struct M_Code_EditorInternalData;
    M_Code_EditorInternalData* m_pData;
};

#endif
